package DAO;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.*;
import java.util.Calendar;

import Pojo.Aluno;
import Pojo.Atividade;
import Pojo.HistoricoTurma;
import Pojo.Turma;
import Pojo.Nota;

/**Classe AtividadeDao
 * Essa classe implementa a interface AtividadeDao para comunicar com arquivos.
 * @author Ronan Lopes
 *
 */
public class AtividadeDaoImplArquivo implements AtividadeDao {
	
	/** Lista de Atividades*/
	private List<Atividade> listaAtividades;
	
	/** tributo constante com o endereço do arquivo onde será armazenada os dados.*/
	private static final String nomeArquivo = "Arquivos/Atividades.txt";
	
	/** Atributo onde é guardado o próximo id para inserção na lista.*/
	private int proximoId;
	
	/**
	 * Construtor da classe com um identificador indicando que não é necessário buscar dados do arquivo
	 * @param identificador
	 */
	public AtividadeDaoImplArquivo(int identificador){
		this.listaAtividades = new ArrayList<Atividade>();
	}
	
	/**
	 *  Construtor da classe que busca dados no arquivo
	 */
	public AtividadeDaoImplArquivo(){
		this.listaAtividades = new ArrayList<Atividade>();
		this.proximoId=0;
		this.buscarArmazenamento();
	}
	
	/**
	 * Getter do próximo id da Atividade
	 * @return próximo id disponível
	 */
	public int getProximoId(){
		return(this.proximoId);
	}
	
	/**
	 * Lista de Atividades.
	 * @return Lista das Atividades.
	 */
	public List<Atividade> getListaAtividade(){
		return(this.listaAtividades);
	}
	
	/**
	 * Busca Armazenamento no arquivo, trata os dados e monta a lista de atividades.
	 */
	private void buscarArmazenamento(){
		try{
			this.listaAtividades = new ArrayList<Atividade>();
			FileReader arq = new FileReader(nomeArquivo);		//Cria objeto arquivo
		    BufferedReader lerArq = new BufferedReader(arq);	//Cria objeto de leitura
		    String linha=lerArq.readLine();
		    Atividade atividade;
		    String dados[];
		    List<Nota> listaNotas = new ArrayList<Nota>(); 
		    Turma turmaAux;
		    while (linha != null) {
		    	dados = linha.split("\t");
		    	try {  
		    		String str_date=dados[3];
		    		DateFormat formatter ; 
		    		Date date ; 
			    	formatter = new SimpleDateFormat("dd/MM/yyyy");
			    	date = (Date)formatter.parse(str_date); 
			    	Calendar cal=Calendar.getInstance();
			    	cal.setTime(date);
			    	turmaAux = this.buscarTurma(Integer.parseInt(dados[5]));
			    	listaNotas = this.buscarNotas(Integer.parseInt(dados[0]));
			    	atividade = new Atividade(Integer.parseInt(dados[0]),dados[1],dados[2],cal,Double.parseDouble(dados[4]),turmaAux,listaNotas);
			    	this.listaAtividades.add(atividade);
			    	this.proximoId=Integer.parseInt(dados[0]);
		    	} catch (ParseException e){
		    		System.out.println("Exception :"+e);  
		    	} 	    	
		    	linha = lerArq.readLine();						//Lê as linhas.
		    }
		    this.proximoId++;
		    
		    arq.close();										//Fechando o arquivo
		}catch (IOException e) {
			System.err.printf("Erro ao manipular o arquivo: %s.\n",e.getMessage());
		}
	}
	
	/**
	 * Busca no armazenamento usando a turma. É usado para quando não se quer carregar os dados para a lista.
	 * @param idTurma
	 * @return Lista de Atividades 
	 */
	public List<Atividade> buscarArmazenamentoPorTurma(int idTurma){
		List<Atividade> listaAtividadesTurma = new ArrayList<Atividade>();
		Atividade atividade;
		
		try{
			FileReader arq = new FileReader(nomeArquivo);		//Cria objeto arquivo
		    BufferedReader lerArq = new BufferedReader(arq);	//Cria objeto de leitura
		    String linha=lerArq.readLine();
		    String dados[];
		    
		    while (linha != null) {
		    	dados = linha.split("\t");
		    	if (Integer.parseInt(dados[5])==idTurma){
		    		try {  
			    		String str_date=dados[3];
			    		DateFormat formatter ; 
			    		Date date ; 
				    	formatter = new SimpleDateFormat("dd/MM/yyyy");
				    	date = (Date)formatter.parse(str_date); 
				    	Calendar cal=Calendar.getInstance();
				    	cal.setTime(date);
				    	atividade = new Atividade(Integer.parseInt(dados[0]),dados[1],dados[2],cal,Double.parseDouble(dados[4]));
				    	listaAtividadesTurma.add(atividade);
			    	} catch (ParseException e){
			    		System.out.println("Exception :"+e);
			    	}
		    	} 	    	
		    	linha = lerArq.readLine();						//Lê as linhas.
		    }
		    
		    arq.close();										//Fechando o arquivo
		}catch (IOException e) {
			System.err.printf("Erro ao manipular o arquivo: %s.\n",e.getMessage());
		}
		return(listaAtividadesTurma);
	}
	
	/**
	 * Busca no armazenamento usando o id da Atividade. É usado para quando não se quer carregar os dados para a lista.
	 * @param idTurma
	 * @return Atividade 
	 */
	public Atividade buscarArmazenamentoPorId(int idAtividade){
		Atividade atividade=null;
		
		try{
			FileReader arq = new FileReader(nomeArquivo);		//Cria objeto arquivo
		    BufferedReader lerArq = new BufferedReader(arq);	//Cria objeto de leitura
		    String linha=lerArq.readLine();
		    String dados[];
		    
		    while (linha != null) {
		    	dados = linha.split("\t");
		    	if (Integer.parseInt(dados[0])==idAtividade){
		    		try {  
			    		String str_date=dados[3];
			    		DateFormat formatter ; 
			    		Date date ; 
				    	formatter = new SimpleDateFormat("dd/MM/yyyy");
				    	date = (Date)formatter.parse(str_date); 
				    	Calendar cal=Calendar.getInstance();
				    	cal.setTime(date);
				    	atividade = new Atividade(Integer.parseInt(dados[0]),dados[1],dados[2],cal,Double.parseDouble(dados[4]));
				    	return(atividade);
			    	} catch (ParseException e){
			    		System.out.println("Exception :"+e);
			    	}
		    	} 	    	
		    	linha = lerArq.readLine();						//Lê as linhas.
		    }
		    
		    arq.close();										//Fechando o arquivo
		}catch (IOException e) {
			System.err.printf("Erro ao manipular o arquivo: %s.\n",e.getMessage());
		}
		return(atividade);
	}	
	
	/**
	 * Método usado para Salvar a lista do arquivo. O arquivo é sobrescrito nesse método.
	 */
	private void salvarArmazenamento(){
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(nomeArquivo));
			Iterator<Atividade> i = listaAtividades.iterator();
			
			Atividade atividade;
			while(i.hasNext()){
				atividade = (Atividade) i.next();
				out.write(atividade.toString());
			}
			
			out.close();
		} catch (IOException e) {
			System.err.printf("Erro ao manipular o arquivo: %s.\n",e.getMessage());
		}
	}
	
	/**
	 * Método de adicionar a Atividade na lista. 
	 * É verificado se o código já existe, pois se existir não pode ser adicionado.
	 * Após inserir, o método "salvarArmazenamento()" é chamado
	 * @return true se foi possível inserir ou falso se ele foi encontrado na lista.
	 */
	public boolean adicionarAtividade(Atividade atividade){
		if (atividade.getTurma()==null){
			return (false);
		}else{
			Iterator<Atividade> i = listaAtividades.iterator();
			Atividade atividadeComparacao;
			while(i.hasNext()){
				atividadeComparacao = (Atividade) i.next();
				if (atividadeComparacao.getIdAtividade() == atividade.getIdAtividade()){
					return(false);
				}
			}
			this.listaAtividades.add(atividade);
			this.proximoId++;
			this.salvarArmazenamento();
			return(true);
		}
	}
	
	/**
	 * Método para remover atividade da lista. 
	 * Após remover o método "salvarArmazenamento" é chamado.
	 * @return true se a atividade foi encontrado na lista para ser removido ou false se não foi encontrado.
	 */
	public boolean removerAtividade(Atividade atividade){
		Iterator<Atividade> i = listaAtividades.iterator();
		Atividade atividadeComparacao;
		boolean resultado;
		while(i.hasNext()){
			atividadeComparacao = (Atividade) i.next();
			if (atividadeComparacao.getIdAtividade() == atividade.getIdAtividade()){
				resultado = this.listaAtividades.remove(atividadeComparacao);
				this.salvarArmazenamento();
				return(resultado);
			}
		}
		return(false);
	}
	
	/**
	 * Pesquisa de Atividade passando o nome
	 * @param nome
	 * @return Lista de Atividades cujos nomes são iguais às atividades passadas
	 */
	public List<Atividade> procurarPorNome(String nome){
		List<Atividade> listaAtividadesNome = new ArrayList<Atividade>();
		
		Iterator<Atividade> i = listaAtividades.iterator();
		Atividade atividade;
		while(i.hasNext()){
			atividade = (Atividade) i.next();
			if (atividade.getNome().equals(nome)){
				listaAtividadesNome.add(atividade);
			}
		}
		
		return(listaAtividadesNome);
	}

	/**
	 * Pesquisa de Atividade passando a data
	 * @param data
	 * @return Lista de Atividades cujas datas coincidem com o que foi passado por parâmetro. 
	 * 
	 */
	public List<Atividade> procurarPorData(Calendar data){
		List<Atividade> listaAtividadesData = new ArrayList<Atividade>();
		Iterator<Atividade> i = listaAtividades.iterator();
		Atividade atividade;
		while(i.hasNext()){
			atividade = (Atividade) i.next();
			if (atividade.getData().equals(data)){
				listaAtividadesData.add(atividade);
			}
		}
		return(listaAtividadesData);
	}
	
	/**
	 * Método que procura Atividades passando o id de uma Turma
	 * @param idTurma
	 * @return Lista de Atividades cujos códigos das turmas coincidem com o que foi passado por parâmetro.
	 */
	public List<Atividade> procurarPorTurma(int idTurma){
		List<Atividade> listaAtividadesTurma = new ArrayList<Atividade>();
		Iterator<Atividade> i = listaAtividades.iterator();
		Atividade atividade;
		while(i.hasNext()){
			atividade = (Atividade) i.next();
			if (atividade.getTurma().getIdTurma() == idTurma){
				listaAtividadesTurma.add(atividade);
			}
		}
		return(listaAtividadesTurma);
	}
	
	/**
	 * Método que procura atividades passando o id de uma atividade.
	 * @param idAtividade
	 * @return Atividade cujo código é o mesmo que foi passado por parâmetro
	 */
	public Atividade procurarPorId(int idAtividade){
		Iterator<Atividade> i = this.listaAtividades.iterator();
		Atividade atividade;
		while(i.hasNext()){
			atividade = (Atividade) i.next();
			if (atividade.getIdAtividade() == idAtividade){
				return(atividade);
			}
		}
		return(null);	
	}
	
	/**
	 * Método para buscar a turma relacionada à atividade.
	 * @param idTurma
	 * @return Turma
	 */
	private Turma buscarTurma(int idTurma){
		TurmaDaoImplArquivo turmaDao = new TurmaDaoImplArquivo(idTurma);
		return(turmaDao.buscarArmazenamentoProcurarPorId(idTurma));
	}
	
	/**
	 * Método paalunosra buscar notas que estão relacionadas à atividades.
	 * @param idAtividade
	 * @return Lista de Notas
	 */
	private List<Nota> buscarNotas(int idAtividade){
		NotaDaoImplArquivo notaDao = new NotaDaoImplArquivo();
		return(notaDao.buscarArmazenamentoPorAtividade(idAtividade));
	}
	
}

